/*
 *  Copyright 2011 Alexey Andreev.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package org.xthl.core;

import org.nop.core.BeanScope;
import org.nop.core.ManagedBean;
import org.nop.sql.DataManager;
import org.nop.sql.DataResult;
import org.nop.sql.QueryBuilder;
import org.nop.util.Injected;
import org.xthl.core.data.DefaultRoleSource;
import org.xthl.core.data.PermissionSource;
import org.xthl.core.data.RolePermissionSource;
import org.xthl.core.data.UserPermissionSource;
import org.xthl.core.data.UserRoleSource;

/**
 *
 * @author Alexey Andreev
 */
@ManagedBean(iface = PermissionChecker.class, scope = BeanScope.REQUEST)
public class PermissionCheckerImpl implements PermissionChecker {
    private DataManager dataManager;
    private QueryBuilder qb;
    
    @Injected
    public PermissionCheckerImpl(DataManager dataManager) {
        this.dataManager = dataManager;
        this.qb = dataManager.getQueryBuilder();
    }

    @Override
    public boolean checkPermission(Integer userId, int permissionId) {
        if (userId == null) {
            DefaultRoleSource defRole = qb.get(DefaultRoleSource.class);
            RolePermissionSource rolePerm = qb.get(RolePermissionSource.class);
            DataResult result = dataManager.exec(qb.with(defRole)
                    .join(rolePerm, rolePerm.roleId().eq(defRole.roleId()))
                    .filter(defRole.type().eq("guest"))
                    .filter(rolePerm.permissionId().eq(permissionId)).take(1)
                    .fetch(rolePerm.roleId()));
            return result.next();
        } else {
            return checkUserPermission(userId, permissionId) || 
                    checkUserPermission(userId, getPermissionId("user.admin"));
        }
    }
    
    private boolean checkUserPermission(int userId, Integer permissionId) {
        UserPermissionSource userPerm = qb.get(UserPermissionSource.class);
        RolePermissionSource rolePerm = qb.get(RolePermissionSource.class);
        UserRoleSource userRole = qb.get(UserRoleSource.class);
        DataResult result = dataManager.exec(qb.with(userPerm)
                .filter(userPerm.userId().eq(userId))
                .filter(userPerm.permissionId().eq(permissionId)).take(1)
                .fetch(userPerm.userId()));
        if (result.next()) {
            return true;
        }
        result = dataManager.exec(qb.with(userRole)
                .join(rolePerm, rolePerm.roleId().eq(userRole.roleId()))
                .filter(userRole.userId().eq(userId))
                .filter(rolePerm.permissionId().eq(permissionId)).take(1)
                .fetch(userRole.userId()));
        return result.next();
    }

    @Override
    public Integer getPermissionId(String permission) {
        PermissionSource perm = qb.get(PermissionSource.class);
        DataResult result = dataManager.exec(qb.with(perm)
                .filter(perm.name().eq(permission))
                .fetch(perm.id()));
        return result.next() ? result.getInt(1) : null;
    }
}
